﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Media;

using GameLibrary;

namespace ArkanoidGame
{

    public enum BonusType
    {
        Initial,
        SuperBall,
        Enlarge,
        Shrink,
        Life
    }

    static class RandomBonusTypeGenerator
    {
        public static BonusType GetRandomBonusType()
        {
            return (BonusType)(new Random(Guid.NewGuid().GetHashCode()).Next(1,5));
        }
    }
    public class Bonus : DynamicElement
    {
        #region  Private Members
        private Color m_outlineColour = BricksSettings.OUTLINE_COLOR;
        private Color m_fillColour = BricksSettings.FILL_COLOR;
        private BonusType m_type = BonusType.Initial;
        private bool m_visible = true;
        private bool m_active = false;
        private Font m_font = new Font(new FontFamily("Consolas"), 12, FontStyle.Bold);
        private TimeSpan m_timeToLive = new TimeSpan(int.MaxValue);
        #endregion

        #region Public Properties
        public Color OutlineColour
        {
            get { return m_outlineColour; }
            set { m_outlineColour = value; }
        }

        public Color FillColour
        {
            get { return m_fillColour; }
            set { m_outlineColour = value; }
        }

        public BonusType Type
        {
            get { return m_type; }
            set { m_type = value; }
        }

        public bool Initial
        {
            get { return (this.Type == BonusType.Initial); }
        }

        public bool Visible
        {
            get { return this.m_visible; }
        }

        public Font Font 
        {
            get { return m_font; }
        }

        public TimeSpan TimeToLive 
        { 
            get { return m_timeToLive; } 
        }

        #endregion


        #region Constructors
        public Bonus(GamePanel owningGame, BonusType type, PointF position)
            : base(owningGame, position,
                    new SizeF(BricksSettings.BONUS_WIDTH, BricksSettings.BONUS_HEIGTH),
                    new PointF(0, BricksSettings.BONUS_VELOCITY_Y),
                    new PointF(0, 0))
        {
            this.Type = type;
        }
        #endregion 


        #region Public Methods
        public new PointF CalculateNextPosition(TimeSpan elapsedTime)
        {
            return
                new PointF(
                    this.Rectangle.X,
                    this.Rectangle.Y + (float)elapsedTime.TotalSeconds * this.Velocity.Y
                );
        }
        #endregion


        #region Private Methods
        private void Activate(BonusType type)
        {
            ArkanoidGame owner = (ArkanoidGame)OwningGame;

            switch (type)
            {
                case BonusType.Initial:
                    break;
                case BonusType.SuperBall:
                    m_timeToLive = new TimeSpan(0, 0, 5);
                    owner.Ball = new Ball(owner, owner.Ball.Rectangle, owner.Ball.Velocity, owner.Ball.Acceleration, true);
                    break;
                case BonusType.Enlarge:
                    m_timeToLive = new TimeSpan(0, 0, 5);
                    owner.Paddle = new Paddle(owner, 
                        owner.Paddle.Position, 
                        new SizeF(owner.Paddle.Size.Width + BricksSettings.BONUS_PAD_WIDTH_INCREMENT, owner.Paddle.Size.Height)); 
                    break;
                case BonusType.Shrink:
                    m_timeToLive = new TimeSpan(0, 0, 5);
                    owner.Paddle = new Paddle(owner,
                        owner.Paddle.Position,
                        new SizeF(owner.Paddle.Size.Width - BricksSettings.BONUS_PAD_WIDTH_INCREMENT, owner.Paddle.Size.Height));
                    break;
                case BonusType.Life:
                    if (owner.HUD.Lives < 5)
                    {
                        owner.HUD.Lives += 1; 
                    }
                    this.Deactivate(this.m_type);
                    break;
                default:
                    break;
            }
        }

        public void Deactivate(BonusType type)
        {
            ArkanoidGame owner = (ArkanoidGame)OwningGame;

            switch (type)
            {
                case BonusType.Initial:
                    break;

                case BonusType.SuperBall:
                    owner.Ball = new Ball(owner, owner.Ball.Rectangle, owner.Ball.Velocity, owner.Ball.Acceleration, false);
                    owner.Bonuses.Remove(this);
                    break;

                case BonusType.Enlarge:
                    owner.Paddle = new Paddle(owner,
                        owner.Paddle.Position,
                        new SizeF(owner.Paddle.Size.Width - BricksSettings.BONUS_PAD_WIDTH_INCREMENT, owner.Paddle.Size.Height));
                    owner.Bonuses.Remove(this);
                    break;
                case BonusType.Shrink:
                    owner.Paddle = new Paddle(owner,
                        owner.Paddle.Position,
                        new SizeF(owner.Paddle.Size.Width + BricksSettings.BONUS_PAD_WIDTH_INCREMENT, owner.Paddle.Size.Height));
                    owner.Bonuses.Remove(this);
                    break;
                case BonusType.Life:
                    owner.Bonuses.Remove(this);
                    break;
                default:
                    break;
            }
        }
        #endregion


        #region IGameElement Implementation
        public override void Draw(TimeSpan elapsedTime, Graphics g)
        {
            switch (m_type)
            {
                case BonusType.Initial:
                    break;
                case BonusType.SuperBall:
                    if (g != null && m_visible)
                    {
                        g.DrawString("SB", m_font, new SolidBrush(Color.Red), this.Position);

                    }
                    break;
                case BonusType.Enlarge:
                    if (g != null && m_visible)
                    {
                        g.DrawString("<>", m_font, new SolidBrush(Color.Cyan), this.Position);

                    }
                    break;
                case BonusType.Shrink:
                    if (g != null && m_visible)
                    {
                        g.DrawString("><", m_font, new SolidBrush(Color.Violet), this.Position);

                    }
                    break;
                case BonusType.Life:
                    if (g != null && m_visible)
                    {
                        g.DrawString("+1", m_font, new SolidBrush(Color.Yellow), this.Position);

                    }
                    break;
                default:
                    break;
            }
        }

        public override void Update(TimeSpan elapsedTime)
        {

            ArkanoidGame owner = (ArkanoidGame)this.OwningGame;
            this.Position = CalculateNextPosition(elapsedTime);


            if (this.Rectangle.Bottom > owner.Paddle.Rectangle.Top
                && Position.X + this.Size.Width > owner.Paddle.Rectangle.Left
                && Position.X < owner.Paddle.Rectangle.Right)
            {
                this.Activate(m_type); 
                this.m_visible = false;
                this.m_active = true;
                this.Velocity = new PointF(0, 0);
                this.Position = new PointF(0, 0);
                using (var soundPlayer = new SoundPlayer(Properties.Resources._1up))
                {
                    soundPlayer.Play();
                }




                string text = m_type.ToString() + " activated!";
                SizeF textSize = owner.CreateGraphics().MeasureString(text, owner.Font);

                owner.HUD.FloatingTextItems.Add(
                    new FloatText(
                        owner,
                        text,
                        owner.Font,
                        owner.HUD.ForeColour,
                        new PointF(
                            owner.InitialGameSize.Width / 2f - textSize.Width / 2f,
                            owner.InitialGameSize.Height / 2f - textSize.Height / 2f
                        ),
                        new PointF(0, -15),
                        new TimeSpan(0, 0, 2)
                    )
                );




            }

            if (m_active)
            {
                m_timeToLive -= elapsedTime;
            }

            if (m_timeToLive.TotalSeconds <= 0 && m_active)
            {

                this.Deactivate(m_type);
                string text = m_type.ToString() + " deactivated!";
                SizeF textSize = owner.CreateGraphics().MeasureString(text, owner.Font);

                owner.HUD.FloatingTextItems.Add(
                    new FloatText(
                        owner,
                        text,
                        owner.Font,
                        owner.HUD.ForeColour,
                        new PointF(
                            owner.InitialGameSize.Width / 2f - textSize.Width / 2f,
                            owner.InitialGameSize.Height / 2f - textSize.Height / 2f
                        ),
                        new PointF(0, -15),
                        new TimeSpan(0, 0, 2)
                    )
                );


            }


            if (Position.Y + this.Size.Height > owner.HUD.Rectangle.Top)
            {
                owner.Bonuses.Remove(this);
            }
        }
        #endregion
    }

}

